#include <GL/glew.h>
#include "KDWidget.h"
#include <glm/gtc/matrix_transform.hpp>
#include <QtGui/QtEvents>
#include "MGlobalDef.h"
#include <iostream>
#include <fstream>
#include <array>

mgl::KDWidget::KDWidget(int width, int height, QWidget* parent /*= nullptr*/) :
	QGLWidget(QGLFormat(QGL::DoubleBuffer|QGL::DepthBuffer),parent),
	m_camera(glm::vec3(0.f,0.f,1.f), glm::vec3(0.f, 0.f, -1.f), glm::vec3(0.f,1.f,0.f), 1.f, width, height, 0.01f, 100.f)
{
	resize(width, height);
	m_moveSpeed = 0.1f;
	m_rotateSpeed = 0.1f;
	setWindowTitle(QString("KDDBG - debug a kdtree"));
	setWindowFlags(Qt::Dialog | Qt::WindowMinimizeButtonHint);
	m_step = 0;
}

void mgl::KDWidget::initializeGL()
{
	if(glewInit() != GLEW_OK)
		printf("glew init failed\n");

	glClearColor(0.f, 0.2f, 0.3f, 1.f);
	glShadeModel(GL_SMOOTH);
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE);

	glGenVertexArrays(1, &m_vao);
	glBindVertexArray(m_vao);

	m_entityShader.createShader("shaders/entity");
	m_cubeShader.createShader("shaders/cube");

	m_model.readFile("../models/bunny.ply", true);
	m_model.createBuffer();

	m_line.createBuffer();

	//read 
	m_ifs.open("../mraySub/kdlog.bin", std::ios::in | std::ios::binary);
}

void mgl::KDWidget::resizeGL(int w, int h)
{
	glViewport(0,0,w,h);
	m_camera.resize(w, h);
}

void mgl::KDWidget::paintGL()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	m_entityShader.use();
	m_entityShader.param("color",				glm::vec3(1.f,1.f,1.f));
	m_entityShader.param("MVP",					m_camera.getMVP(glm::mat4(1.f)));
	m_entityShader.param("M",					glm::mat4(1.f));
	m_entityShader.param("ambientLight",		glm::vec3(0.2f,0.2f,0.2f));
	m_entityShader.param("directionalLight",	glm::vec3(0.6f, 0.6f, 0.6f));
	m_entityShader.param("directionalDir_w",	glm::normalize(glm::vec3(-1.f,-1.f,-1.f)));
	m_entityShader.param("cameraPosition_w",	m_camera.getPosition());
	m_model.draw();

	m_cubeShader.use();
	m_cubeShader.param("MVP",					m_camera.getMVP(glm::mat4(1.f)));
	m_cubeShader.param("color",					glm::vec4(0.f,0.f,1.f,1.f));

	for(auto& inte : m_kdInters)
		inte.drawWire();
	
	if(m_kdInters.empty() == false){
		m_cubeShader.param("color",				glm::vec4(0.7f, 0.f, 0.4f, 0.5f));
		m_kdInters.back().drawCube();
	}

	m_cubeShader.param("color", glm::vec4(1.f,0.f,0.f,1.f));
	m_line.draw();
}

void mgl::KDWidget::keyPressEvent(QKeyEvent * event)
{
	m_needRefresh = true;
	switch (event->key()){
	case Qt::Key_W:
		m_camera.move(m_camera.getLook(), m_moveSpeed);
		break;
	case Qt::Key_S:
		m_camera.move(m_camera.getLook(), -m_moveSpeed);
		break;
	case Qt::Key_A:
		m_camera.move(m_camera.getRight(), -m_moveSpeed);
		break;
	case Qt::Key_D:
		m_camera.move(m_camera.getRight(), m_moveSpeed);
		break;

	case Qt::Key_Up:
		m_camera.rotate(m_camera.getRight(), m_rotateSpeed);
		break;
	case Qt::Key_Down:
		m_camera.rotate(m_camera.getRight(), -m_rotateSpeed);
		break;
	case Qt::Key_Left:
		m_camera.rotate(AXIS_Y, m_rotateSpeed);
		break;
	case Qt::Key_Right:
		m_camera.rotate(AXIS_Y, -m_rotateSpeed);
		break;

	case Qt::Key_B:
		{
			std::array<float, 6> tmp;
			if(m_ifs.eof() == false){
				m_ifs.read(reinterpret_cast<char*>(tmp.data()), sizeof(tmp));
				m_kdInters.push_back(KDInter(tmp));
				m_kdInters.back().setType(KDInter::Wire);
				m_kdInters.back().createBuffer();
				m_step++;
			}
			std::cout << "step:" << m_step << std::endl;
		}
		break;
	default:
		m_needRefresh = false;
		break;
	}

	if(m_needRefresh){
		update();
	}
}

mgl::KDWidget::~KDWidget()
{
	glDeleteVertexArrays(1, &m_vao);
}
